package menupopupplugin2.popup.actions;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.ParserConfigurationException;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.xml.sax.SAXException;

import util.ConnectionConfig;

import core.Main;

public class ModelLayerAction implements IObjectActionDelegate {

	private Shell shell;

	/**
	 * Constructor for Action1.
	 */
	public ModelLayerAction() {
		super();
	}

	/**
	 * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
	 */
	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
		shell = targetPart.getSite().getShell();
	}

	/**
	 * @see IActionDelegate#run(IAction)
	 */
	public void run(IAction action) {
		IWorkbenchWindow window = PlatformUI.getWorkbench()
				.getActiveWorkbenchWindow();

		IStructuredSelection selection = (IStructuredSelection) window
				.getSelectionService().getSelection();
		Object firstElement = selection.getFirstElement();
		final IPath path;

		if ((firstElement instanceof IAdaptable)) {
			IResource selectedResource = (IResource) ((IAdaptable) firstElement)
					.getAdapter(IResource.class);

			path = selectedResource.getLocation();

		} else {
			MessageDialog.openInformation(shell, "Information",
					"Have error when recognize file\n" + "Please check it");
			return;
		}

		ModelLayerWizard wizard = new ModelLayerWizard(path.toString());
		WizardDialog wizardDialog = new WizardDialog(shell, wizard);
		if (wizardDialog.open() == Window.OK) {
			ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell);
			try {
				dialog.run(true, true, new RunnableWithProgressImpl(wizard,
						path.toString()));
			} catch (InvocationTargetException e) {
				e.printStackTrace();
				MessageDialog.openError(shell, "Error", "Any Error there");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	private class RunnableWithProgressImpl implements IRunnableWithProgress {
		private ModelLayerWizard wizard;
		private String path;

		public RunnableWithProgressImpl(ModelLayerWizard wizard, String path) {
			this.wizard = wizard;
			this.path = path;
		}

		public void run(IProgressMonitor monitor) {
			monitor.beginTask("Wating for generate model layer class ...", 60);

			ConnectionConfig connConfig = null;
			boolean isHibernate = wizard.persistentLayerChoosePage
					.isHibernate();

			// execute the task ...

			String connectionURL = wizard.inputConnectionURLPage
					.getConnectionURL();
			String user = wizard.inputConnectionURLPage.getUsername();
			String password = wizard.inputConnectionURLPage.getPassword();

			connConfig = analyzeConnectionURL(connectionURL, user, password);
			System.out.println("conn Config " + connConfig);

			if (connConfig == null) {
				Display.getDefault().syncExec(new Runnable() {
					@Override
					public void run() {
						MessageDialog.openError(shell, "Error",
								"Please input a suitable connection URL");
					}
				});

				monitor.done();
				return;
			}
			String packageName = wizard.inputPackageNamePage.getPackageName();

			Main m = null;
			try {
				m = new Main(path, packageName, monitor, shell);
			} catch (final ParserConfigurationException e) {
				Display.getDefault().syncExec(new Runnable() {
					@Override
					public void run() {
						MessageDialog.openError(shell, "Error", e.getMessage());
					}
				});
			} catch (final SAXException e) {
				Display.getDefault().syncExec(new Runnable() {
					@Override
					public void run() {
						MessageDialog.openError(shell, "Error", e.getMessage());
					}
				});
			} catch (final IOException e) {
				Display.getDefault().syncExec(new Runnable() {
					@Override
					public void run() {
						MessageDialog.openError(shell, "Error", e.getMessage());
					}
				});
			}

			if (m != null) {
				m.setConnectionConfig(connConfig);
				try {
					m.generate(path, !isHibernate, false);
				} catch (final Exception e) {
					e.printStackTrace();
					Display.getDefault().syncExec(new Runnable() {
						@Override
						public void run() {
							if (e.getMessage() == null
									|| "".equals(e.getMessage()))
								MessageDialog.openError(shell, "Error",
										"Have error when generate file!");
							else
								MessageDialog.openError(shell, "Error",
										e.getMessage());
						}
					});
				}
			}
			// ------------------
			monitor.done();
		}
	}

	private ConnectionConfig analyzeConnectionURL(String connectionURL,
			String user, String password) {
		ConnectionConfig connConfig = new ConnectionConfig();
		connConfig.setUser(user);
		connConfig.setPassword(password);

		Pattern pattern = Pattern
				.compile("jdbc:([a-z]+)://([a-z]+|[0-9\\.]+):([0-9]+)/([a-zA-Z_]+)");
		Matcher match = pattern.matcher(connectionURL);
		if (match.matches() == false)
			return null;

		if (match.groupCount() < 4)
			return null;

		connConfig.setTypeOfDBS(match.group(1));
		connConfig.setServerName(match.group(2));
		connConfig.setPort(match.group(3));
		connConfig.setDatabaseName(match.group(4));

		return connConfig;
	}

	@Override
	public void selectionChanged(IAction arg0, ISelection arg1) {

	}
}
